package com.fenger.billbar.demo;

import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.URL;

import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.universe.*;

import javax.imageio.ImageIO;
import javax.media.j3d.*;
import javax.vecmath.*;

import com.sun.j3d.utils.geometry.Sphere;
import com.sun.j3d.utils.image.TextureLoader;

import javax.swing.Timer;

/*
 * Java 3D 和 Swing
 Canvas3D利用了你机器的显示卡增强性能。不幸的是，这说明它不能很好地和Sun的swing用户界面组件混合。
 这些组件被称为“轻量”。轻量组件会被Canvas3D遮蔽即使想要把它们放在前方。 这是解决这个问题的几个方案:
 · 你可以在同屏中混合使用轻量和重量组件，只要让它们在不同的容器中。
 · 如果你使用弹出式菜单，JPopupMenu类的一个静态函数可以解决这个问题:
 setDefaultLightWeightPopupEnabled(false);
 · 你可以使用老式的AWT组件代替swing。 动画和交互 – 跳动的小球想要制作动画你就要在动画的每一帧间
 移动物体。你可以使用计时器并且每次经过一个很短的时间移动物体。你也可以用其它方式修改物体，下面的
 例子缩放了小球使它看起来在每次碰撞时被压扁。 为了和用户交互，你可以处理按键或按钮点击或其它组件。
 有一点需要注意的是你必须通过设置功能属性告诉Java 3D你要移动物体。否则一旦物体被绘制你将不能再移动它们。
 objTrans = new TransformGroup();
 objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
 下面的例子组合了这些技术。点击按钮使它启动，小球开始上下跳动，然后你可以按下a或s左右移动小球。

 */
public class BouncingBall extends Applet implements ActionListener, KeyListener {
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private Button go = new Button("Go");
	private TransformGroup objTrans;
	private Transform3D trans = new Transform3D();
	private float height = 0.0f;
	private float sign = 1.0f; // going up or down
	private Timer timer;
	private float xloc = 0.0f;
	public BranchGroup createSceneGraph() {
		// >创建分支图的根
		BranchGroup objRoot = new BranchGroup();
		objTrans = new TransformGroup();
		objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
		objRoot.addChild(objTrans);
		
		// 定义物体的外观特性
		Appearance app = new Appearance();
		BufferedImage image = null;
		try {
			// image = ImageIO.read(new
			// File("D:/new_code_workspace/MyTest/src/res/ball-hdpi/ball2.png"));
			image = ImageIO.read(ClassLoader.getSystemClassLoader().getResource("res/ball-hdpi/ball_orange_solid.bmp"));
		} catch (IOException e) {
			e.printStackTrace();
		}
		TextureLoader texloader = new TextureLoader(image, new String("RGB"));
		app.setTexture(texloader.getTexture());
		Material material = new Material();// 表面材质
		material.setDiffuseColor(new Color3f(0.0f, 0.0f, 0.0f));// 定义散射效果
		material.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
		app.setMaterial(material);// 将材质属性加入到外观对象中
		// >创建一个简单图形叶子节点，添加到场景图。
		Sphere sphere = new Sphere(0.25f,-13,100);
		sphere.setAppearance(app);
		objTrans = new TransformGroup();
		objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
		Transform3D pos1 = new Transform3D();
		pos1.setTranslation(new Vector3f(0.0f, 0.0f, 0.0f));
		objTrans.setTransform(pos1);
		objTrans.addChild(sphere);
		objRoot.addChild(objTrans);
		BoundingSphere bounds =	new BoundingSphere(new Point3d(0.0, 0.0, 0.0), 100.0);
		Color3f light1Color = new Color3f(1.0f, 0.0f, 0.2f);
		Vector3f light1Direction = new Vector3f(4.0f, -7.0f, -12.0f);
		DirectionalLight light1	= new DirectionalLight(light1Color, light1Direction);
		light1.setInfluencingBounds(bounds);
		objRoot.addChild(light1);
		// >设置环境光
		Color3f ambientColor = new Color3f(0.0f, 0.0f, 0.0f);
		AmbientLight ambientLightNode = new AmbientLight(ambientColor);
		ambientLightNode.setInfluencingBounds(bounds);
		objRoot.addChild(ambientLightNode);
		return objRoot;
	}

	public BouncingBall() {
		setLayout(new BorderLayout());
		GraphicsConfiguration config = SimpleUniverse.getPreferredConfiguration();
		Canvas3D canvas = new Canvas3D(config);
		add("Center", canvas);
		canvas.addKeyListener(this);
		timer = new Timer(100, this);
		// timer.start();
		Panel p = new Panel();
		p.add(go);
		add("North", p);
		go.addActionListener(this);
		go.addKeyListener(this);
		// >创建一个简单场景附加到虚拟宇宙
		BranchGroup scene = createSceneGraph();
		SimpleUniverse u = new SimpleUniverse(canvas);
		u.getViewingPlatform().setNominalViewingTransform();
		u.addBranchGraph(scene);
	}

	public void keyPressed(KeyEvent e) {
		// >按键被按下时调用
		if (e.getKeyChar() == 's') {
			System.out.print("key 's' is pressed!\n");
			xloc = xloc + .01f;
		}
		if (e.getKeyChar() == 'a') {
			System.out.print("key 'a' is pressed!\n");
			xloc = xloc - .01f;
		}
	}

	public void keyReleased(KeyEvent e) {
		// >按键放开是被调用
	}

	public void keyTyped(KeyEvent e) {
		// >按一个键时调用
	}

	public void actionPerformed(ActionEvent e) {
		// >按钮按下时启动计时器
		if (e.getSource() == go) {
			if (!timer.isRunning()) {
				timer.start();
			}
		}else {
			height += .1 * sign;
			if (Math.abs(height * 2) >= 1)
				sign = -1.0f * sign;
			if (height < -0.4f) {
				trans.setScale(new Vector3d(1.0, .8, 1.0));
			}else {
				trans.setScale(new Vector3d(1.0, 1.0, 1.0));
			}
			trans.setTranslation(new Vector3f(xloc, height, 0.0f));
			objTrans.setTransform(trans);
		}
	}

	public static void main(String[] args) {
		System.out.println("Program Started");
		BouncingBall bb = new BouncingBall();
		bb.addKeyListener(bb);
		MainFrame mf = new MainFrame(bb, 600, 800);
	}
}
